@tool
extends Control

const TWO: Vector2 = Vector2(2, 2)
const LINE_WIDTH_PERCENT: float = 0.05

@export var period: float

var _timer: float

var _ratio: Vector2
var _w: Vector2
var _h: Vector2
var _phase: Array[float]
var _line_width: float
var _line_length: float
var _stride: float

func _enter_tree() -> void:
	on_resize()


func _notification(what: int) -> void:
	if what == NOTIFICATION_RESIZED:
		on_resize()
	elif what == NOTIFICATION_VISIBILITY_CHANGED:
		set_process(visible)


func _process(delta: float) -> void:
	_timer += delta
	queue_redraw()


func _draw() -> void:
	var half_lw := 0.5 * _line_width
	var o := _timer / period
	
	var times := []

	for i in range(0, 2):
		times.push_back(o + i * _stride)
		times.push_back(o + i * _stride + _line_length)
	
	var points := []
	for i in range(0, times.size(), 2):
		var begin := get_point(times[i])
		var end := get_point(times[i + 1])
		points.push_back(begin)
		if absf(begin.x - end.x) > 0.1 and absf(begin.y - end.y) > 0.1:
			var middle := get_next_corner(times[i])
			points.push_back(middle + half_lw * (middle - begin).normalized())
			points.push_back(middle + half_lw * (middle - end).normalized())
		
		points.push_back(end)
	
	draw_multiline(PackedVector2Array(points), Color.GOLD, _line_width)


func on_resize():
	var rect := get_rect()
	_ratio = rect.size / rect.size.dot(TWO)
	_w = Vector2(rect.size.x, 0)
	_h = Vector2(0, rect.size.y)
	_line_width = minf(rect.size.x, rect.size.y) * LINE_WIDTH_PERCENT
	_line_length = 0.9 * minf(_ratio.x, _ratio.y)
	_stride = _ratio.dot(Vector2.ONE)
	_phase = [
		_ratio.dot(Vector2.RIGHT), 
		_ratio.dot(Vector2.ONE),
		_ratio.dot(Vector2(2, 1)),
		_ratio.dot(TWO)
	]


func get_point(t: float) -> Vector2:
	if (is_zero_approx(t)):
		return Vector2.ZERO
	t -= floorf(t)
	if t <= _phase[0]:
		return (t / _ratio.x) * _w
	elif t <= _phase[1]:
		return _w + ((t - _ratio.x) / _ratio.y) * _h
	elif t <= _phase[2]:
		return ((_ratio.dot(Vector2(2, 1)) - t) / _ratio.x) * _w + _h
	else:
		return ((_ratio.dot(TWO) - t) / _ratio.y) * _h;
	

func get_next_corner(t: float) -> Vector2:
	t -= floorf(t)
	if t <= _phase[0]:
		return _w
	elif t <= _phase[1]:
		return _w + _h
	elif t <= _phase[2]:
		return _h
	else:
		return Vector2.ZERO
